use axum::{
    body::Body,
    extract::{Path, Query, State},
    http::Response,
    response::IntoResponse,
    Json,
};
use sea_orm::query;
use sky_pojo::{
    dto::{
        self,
        address::{self, AddressDTO, SearchDTO, SetDefaultDTO},
    },
    entities::address_book::Model,
};

use crate::{bootstrap::AppState, middleware::jwt::user::Claims, router::resp::RespVO, service};

pub async fn list(State(state): State<AppState>, claims: Claims) -> Response<Body> {
    match service::address_book::list(
        &state.db_pool,
        SearchDTO {
            user_id: claims.id,
            is_default: false,
        },
    )
    .await
    {
        Ok(vec) => RespVO::<Vec<Model>>::success("".to_owned(), Some(vec)).into_response(),
        Err(e) => RespVO::<Vec<Model>>::error_without_data(e).into_response(),
    }
}

pub async fn save(
    State(state): State<AppState>,
    claims: Claims,
    Json(dto): Json<AddressDTO>,
) -> Response<Body> {
    match service::address_book::save(&state.db_pool, dto, claims.id).await {
        Ok(model) => RespVO::<Model>::success("".to_owned(), Some(model)).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn get_by_id(
    State(state): State<AppState>,
    Path(id): Path<i64>,
    _claim: Claims,
) -> Response<Body> {
    match service::address_book::get_by_id(&state.db_pool, id).await {
        Ok(model) => RespVO::<Model>::success("".to_owned(), Some(model)).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn update(
    State(state): State<AppState>,
    claims: Claims,
    Json(dto): Json<AddressDTO>,
) -> Response<Body> {
    match service::address_book::update(&state.db_pool, dto.into(), claims.id).await {
        Ok(model) => RespVO::<Model>::success("".to_owned(), Some(model)).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }

    // RespVO::<()>::error_without_data("".to_string()).into_response()
}

pub async fn set_default(
    State(state): State<AppState>,
    claims: Claims,
    Json(dto): Json<SetDefaultDTO>,
) -> Response<Body> {
    match service::address_book::update(&state.db_pool, dto.into(), claims.id).await {
        Ok(model) => RespVO::<Model>::success("".to_owned(), Some(model)).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn delete_by_id(
    State(state): State<AppState>,
    claims: Claims,
    Query(query): Query<address::DeleteById>,
) -> Response<Body> {
    match service::address_book::delete_by_id(&state.db_pool, query.id, claims.id).await {
        Ok(rows) => RespVO::<u64>::success("".to_owned(), Some(rows)).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn get_default(State(state): State<AppState>, claims: Claims) -> Response<Body> {
    match service::address_book::list(
        &state.db_pool,
        SearchDTO {
            user_id: claims.id,
            is_default: true,
        },
    )
    .await
    {
        Ok(model) => RespVO::<Vec<Model>>::success("".to_owned(), Some(model)).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}
